package pe.edu.upc.dew.bibliotecaweb.dao;

import java.sql.Statement;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import pe.edu.upc.dew.bibliotecaweb.model.Libro;

/**
 * Clase LibroDao, contiene la implementacion de metodos que acceden a la BD para procesar
 * u obtener informacion de los libros.
 * @author DEW 2010
 */
public class LibroDao {

    private List<Libro> libros;

    /**
     * Metodo que busca en un listado de libros alguna aproximacion con respecto al parametro que se indica
     * @param cadena, contiene el titulo referencial por el cual se desea realizar la busqueda
     * @return, devuelve un listado de todos los libros que coincidan con el titulo ingresado
     */
    public List<Libro> getLibroPorTitulo(String cadena) {
        cadena = cadena.trim();

        libros = new ArrayList<Libro>();

        libros = this.getLibrosBD();

        if (cadena.equals("")) {
            return libros;
        } else {
            List<Libro> librosfinal = new ArrayList<Libro>();
            for (Libro lib : libros) {
                if (lib.getTituloLibro().toLowerCase().contains(cadena.toLowerCase())) {
                    librosfinal.add(lib);
                }
            }
            return librosfinal;
        }
    }

    /**
     * Implementa la logica necesaria para validar los datos del libro
     * @param libro objeto libro con los datos a verificar
     * @return devuelve un valor verdadero si ya existe por lo menos un libro con el mismo titulo o codigo 
     *         ISBN que se intenta registrar, de lo contrario retorna falso
     */
    public boolean existeLibro(Libro libro) {
        libros = new ArrayList<Libro>();

        libros = this.getLibrosBD();

        if (libros.size() == 0) {
            return false;
        } else {
            for (Libro lib : libros) {
                if ((lib.getTituloLibro().toLowerCase().equals(libro.getTituloLibro().trim().toLowerCase())) ||
                        (lib.getCodigoIsbn().toLowerCase().equals(libro.getCodigoIsbn().trim().toLowerCase()))) {
                    return true;
                }
            }
            return false;
        }
    }

    /**
     * Metodo que accede a BD para obtener todos los libros registrados en la tabla correspondiente
     * @return devuelve un listado de objetos de tipo libro
     */
    private List<Libro> getLibrosBD() {
        libros = new ArrayList<Libro>();
        Libro libro = null;
        Connection cnt = null;
        PreparedStatement pst = null;
        ResultSet rs = null;
        try {
            System.out.println("Entrando al try de LibroDao - getLibrosBD");
            cnt = ConnectionUtils.getConnection();
            pst = cnt.prepareStatement("SELECT L.IDLIBRO, L.TITULOLIBRO, L.TEMALIBRO, L.CODIGOISBN, L.NOMBREEDITORIAL, L.ANIOPUBLICACION, " +
                    "L.NOMBREAUTOR, COUNT(IDEJEMPLAR) AS NUMEJEM FROM EJEMPLAR E RIGHT OUTER JOIN LIBRO L ON E.IDLIBRO = L.IDLIBRO AND " +
                    "E.ESTADOEJEMPLAR = 'D' GROUP BY L.IDLIBRO, L.TITULOLIBRO, L.TEMALIBRO, L.CODIGOISBN, L.NOMBREEDITORIAL, " +
                    "L.ANIOPUBLICACION, L.NOMBREAUTOR");
            rs = pst.executeQuery();
            while (rs.next()) {
                libro = new Libro();
                libro.setIdLibro(rs.getInt("IDLIBRO"));
                libro.setTituloLibro(rs.getString("TITULOLIBRO"));
                libro.setTemaLibro(rs.getString("TEMALIBRO"));
                libro.setCodigoIsbn(rs.getString("CODIGOISBN"));
                libro.setNombreEditorial(rs.getString("NOMBREEDITORIAL"));
                libro.setAnioPublicacion(rs.getString("ANIOPUBLICACION"));
                libro.setNombreAutor(rs.getString("NOMBREAUTOR"));
                libro.setNumEjem(rs.getInt("NUMEJEM"));
                libros.add(libro);
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            ConnectionUtils.closeResultSet(rs);
            ConnectionUtils.closePreparedStatement(pst);
            ConnectionUtils.closeConnection(cnt);
        }
        return libros;
    }

    /**
     * Metodo que en base al codigo del libro retorna un objeto de tipo libro
     * @param idLibro identificador del libro del cual se desean obtener todos sus datos
     * @return devuelve un objeto de tipo libro
     */
    public Libro getLibroPorId(int idLibro) {
        Libro libro = null;
        Connection cnt = null;
        Statement st = null;
        ResultSet rs = null;
        try {
            cnt = ConnectionUtils.getConnection();
            st = cnt.createStatement();
            rs = st.executeQuery("SELECT L.IDLIBRO, L.TITULOLIBRO, L.TEMALIBRO, L.CODIGOISBN, L.NOMBREEDITORIAL, L.ANIOPUBLICACION," +
                    "L.NOMBREAUTOR, COUNT(IDEJEMPLAR) AS NUMEJEM FROM EJEMPLAR E, LIBRO L WHERE E.IDLIBRO = L.IDLIBRO AND L.IDLIBRO = " + idLibro +
                    "AND E.ESTADOEJEMPLAR = 'D' GROUP BY L.IDLIBRO, L.TITULOLIBRO, L.TEMALIBRO, L.CODIGOISBN, L.NOMBREEDITORIAL, " +
                    "L.ANIOPUBLICACION, L.NOMBREAUTOR");
            if (rs.next()) {
                libro = new Libro();
                libro.setIdLibro(rs.getInt("IDLIBRO"));
                libro.setTituloLibro(rs.getString("TITULOLIBRO"));
                libro.setTemaLibro(rs.getString("TEMALIBRO"));
                libro.setCodigoIsbn(rs.getString("CODIGOISBN"));
                libro.setNombreEditorial(rs.getString("NOMBREEDITORIAL"));
                libro.setAnioPublicacion(rs.getString("ANIOPUBLICACION"));
                libro.setNombreAutor(rs.getString("NOMBREAUTOR"));
                libro.setNumEjem(rs.getInt("NUMEJEM"));
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            ConnectionUtils.closeResultSet(rs);
            ConnectionUtils.closeStatement(st);
            ConnectionUtils.closeConnection(cnt);
        }
        return libro;
    }

    /**
     * Implementa la logica para acceder a la BD y registrar en la tabla correspondiente los datos del libro.     
     * @param libro objeto libro con todos los datos poblados que van a ser registrados en la tabla de la BD
     */
    public void add(Libro libro) {
        Connection cnt = null;
        Statement st = null;
        try {
            cnt = ConnectionUtils.getConnection();
            st = cnt.createStatement();

            st.execute("INSERT INTO LIBRO (TITULOLIBRO, TEMALIBRO, CODIGOISBN, NOMBREEDITORIAL, " +
                    "ANIOPUBLICACION, NOMBREAUTOR) VALUES ('" +
                    libro.getTituloLibro() + "','" +
                    libro.getTemaLibro() + "','" + libro.getCodigoIsbn() + "','" +
                    libro.getNombreEditorial() + "','" + libro.getAnioPublicacion() + "','" +
                    libro.getNombreAutor() + "')");

            System.out.println("Se registro el libro correctamente");
            //Obtenemos el ultimo codigo del libro.
            libro.setIdLibro(this.getLastIdLibro());
            EjemplarDao ejemplarDao = new EjemplarDao();
            ejemplarDao.add(libro);

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            ConnectionUtils.closeStatement(st);
            ConnectionUtils.closeConnection(cnt);
        }
    }

    /**
     * Implementa la logica para acceder a la BD y obtener el ultimo codigo de los libros
     * @return devuelve el ultimo id del libro registrado en tabla libros
     */
    private Integer getLastIdLibro() {
        Connection cnt = null;
        Statement st = null;
        ResultSet rs = null;
        try {
            cnt = ConnectionUtils.getConnection();
            st = cnt.createStatement();
            rs = st.executeQuery("SELECT Max(Idlibro) AS IDLIBRO from libro");
            if (rs.next()) {
                return (rs.getInt("IDLIBRO"));
            } else {
                return 1;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            ConnectionUtils.closeResultSet(rs);
            ConnectionUtils.closeStatement(st);
            ConnectionUtils.closeConnection(cnt);
        }
        return null;
    }
}
